package sucursal;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ofertas.Oferta;

import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;

import productos.Presentacion;
import productos.StockNoDisponibleExeption;
import clientes.Cliente;
import clientes.ElSaldoDeLaCtaCteEsInsuficienteExeption;
import venta.Venta;

public class TestSucursal {
	Venta venta1;
	Venta venta2;
	DateTime fecha1;
	Sucursal sucursalEnTesteo;
	Map<Presentacion, Integer> productos;
	List<Oferta> ofertas;

	@Before
	public void setup() {

		venta1 = mock(Venta.class);
		sucursalEnTesteo = spy(new Sucursal());

	}

	@Test
	public void testLosCamposDeLaSucursalNoEstanVaciosEsDecirSeInicializoLaClase() {

		assertNotNull(sucursalEnTesteo.clientes());
		assertNotNull(sucursalEnTesteo.ofertas());
		assertNotNull(sucursalEnTesteo.presentaciones());
		assertNotNull(sucursalEnTesteo.ventas());
	}

	@SuppressWarnings("unchecked")
	@Test
	public void testVentaDirectaSeEnvianLosMetodosPara()
			throws StockNoDisponibleExeption, ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {

		productos = mock(Map.class);

		// doReturn(true).when(sucursalEnTesteo.elMetodo());

		Cliente carlos = mock(Cliente.class);
		when(carlos.nombre()).thenReturn("Carlos");
		when(carlos.dni()).thenReturn("35792749");

		sucursalEnTesteo.agregarCliente(carlos);

		sucursalEnTesteo.ventaDirectaCobroCtaCte("Carlos", "35792749",
				productos);

		verify(sucursalEnTesteo, times(1)).verificarStock(productos);
	}

	@Test(expected = StockNoDisponibleExeption.class)
	public void testVentaDirectaSiElStockNoEstaDisponibleRetornaUnaStockNoDisponibleExeption()
			throws StockNoDisponibleExeption {

		productos = new HashMap<Presentacion, Integer>();

		Presentacion producto1 = mock(Presentacion.class);

		productos.put(producto1, 5);
		doThrow(new StockNoDisponibleExeption()).when(producto1)
				.verificarDisponibilidad(5);

		sucursalEnTesteo.verificarStock(productos);
		verify(sucursalEnTesteo, times(1)).verificarStock(productos);
	}

	@Test
	public void testVentaDirectaSiElStockEstaDisponibleNoRetornaUnaExepcion()
			throws StockNoDisponibleExeption {

		productos = new HashMap<Presentacion, Integer>();

		Presentacion producto1 = mock(Presentacion.class);

		productos.put(producto1, 5);

		sucursalEnTesteo.verificarStock(productos);
		verify(sucursalEnTesteo, times(1)).verificarStock(productos);
	}

	@SuppressWarnings("unchecked")
	@Test
	public void testVentaDirectaUnaVezQueHayProductosEnStockSeteaElPagoEnCtaCte()
			throws StockNoDisponibleExeption, ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {
		productos = mock(Map.class);

		Cliente carlos = mock(Cliente.class);
		when(carlos.nombre()).thenReturn("Carlos");
		when(carlos.dni()).thenReturn("35792749");

		sucursalEnTesteo.agregarCliente(carlos);
		assertNull(sucursalEnTesteo.medioDePago());
		sucursalEnTesteo.ventaDirectaCobroCtaCte("Carlos", "35792749",
				productos);
		assertNotNull(sucursalEnTesteo.medioDePago());
		verify(sucursalEnTesteo,times(1)).pagoEnCtaCte();

	}

	@SuppressWarnings("unchecked")
	@Test(expected = ClienteNoEstaCargadoExeption.class)
	public void testSiElClienteNoExisteRetornaUnaClienteNoEstaCargadoExeption()
			throws StockNoDisponibleExeption, ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {
		productos = mock(Map.class);
		sucursalEnTesteo.ventaDirectaCobroCtaCte("Carlos", "35792749",
				productos);

	}

	@SuppressWarnings("unchecked")
	@Test(expected = ClienteNoEstaCargadoExeption.class)
	public void testSiHayUnClienteCargadoYNoEsElMismoRetornaUnaClienteNoEstaCargadoExeption()throws StockNoDisponibleExeption, ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {
		productos = mock(Map.class);
		
		Cliente pedro = mock(Cliente.class);
		when(pedro.nombre()).thenReturn("Pedro");
		when(pedro.dni()).thenReturn("12419446");

		sucursalEnTesteo.agregarCliente(pedro);
		
		sucursalEnTesteo.ventaDirectaCobroCtaCte("Carlos", "35792749",
				productos);

	}
	
	@SuppressWarnings("unchecked")
	@Test
	public void testVentaDirectaEnEfectivo() throws StockNoDisponibleExeption,
			ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {
		productos = mock(Map.class);
		Cliente carlos = mock(Cliente.class);
		when(carlos.nombre()).thenReturn("Carlos");
		when(carlos.dni()).thenReturn("35792749");

		sucursalEnTesteo.agregarCliente(carlos);
		sucursalEnTesteo.ventaDirectaCobroEfectivo("Carlos", "35792749",
				productos);
		assertNotNull(sucursalEnTesteo.medioDePago());
		verify(sucursalEnTesteo, times(1)).buscarCliente("Carlos", "35792749");
	}

	@Test
	public void testVentaDirectaEnEfectivoSinCliente()
			throws StockNoDisponibleExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {
		productos = mock(Map.class);

		sucursalEnTesteo.ventaDirectaCobroEfectivo(productos);
		assertNotNull(sucursalEnTesteo.medioDePago());
	}

	@Test
	public void testVentaADomicilioEnCtaCte() throws StockNoDisponibleExeption,
			ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {

		productos = mock(Map.class);
		Cliente carlos = mock(Cliente.class);
		when(carlos.nombre()).thenReturn("Carlos");
		when(carlos.dni()).thenReturn("35792749");
		sucursalEnTesteo.agregarCliente(carlos);
		sucursalEnTesteo
				.ventaDomicilioEnCtaCte(productos, "Carlos", "35792749");

	}

	@Test
	public void testVentaDirectaCreaUnaADomicilio()
			throws StockNoDisponibleExeption, ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {

		productos = new HashMap<Presentacion, Integer>();

		Presentacion producto1 = mock(Presentacion.class);

		productos.put(producto1, 5);
		doThrow(new StockNoDisponibleExeption()).when(producto1)
				.verificarDisponibilidad(5);
		Cliente carlos = mock(Cliente.class);
		when(carlos.nombre()).thenReturn("Carlos");
		when(carlos.dni()).thenReturn("35792749");
		sucursalEnTesteo.agregarCliente(carlos);

		sucursalEnTesteo.ventaDirectaCobroCtaCte("Carlos", "35792749",
				productos);
		verify(sucursalEnTesteo, times(1)).ventaDomicilioSinStock(productos,
				"Carlos", "35792749");

	}

	@Test
	public void testVerificoVentaADomicilioEnCtaCte()
			throws StockNoDisponibleExeption, ClienteNoEstaCargadoExeption, ElSaldoDeLaCtaCteEsInsuficienteExeption {
		productos = new HashMap<Presentacion, Integer>();
		Presentacion producto1 = mock(Presentacion.class);

		productos.put(producto1, 5);

		Cliente carlos = mock(Cliente.class);
		when(carlos.nombre()).thenReturn("Carlos");
		when(carlos.dni()).thenReturn("35792749");
		sucursalEnTesteo.agregarCliente(carlos);

		sucursalEnTesteo
				.ventaDomicilioEnCtaCte(productos, "Carlos", "35792749");

		assertEquals(1, sucursalEnTesteo.envios().size());

	}
	
	@Test
	public void testVerificoElPrecioDeUnProductoEnOferta(){
		Oferta oferta = mock(Oferta.class);
		ofertas = new ArrayList<Oferta>();
		ofertas.add(oferta);
		Presentacion presentacion = mock(Presentacion.class);
		when(oferta.valorOfertaParaProducto(presentacion)).thenReturn(0D);
		assertTrue(sucursalEnTesteo.precioOfertaParaPresentacion(presentacion) == 0D);
	}

	
}
